import { ethers } from "ethers";
import store from "../store";
import { bankContract, usdtContract ,btcContract, bbContract} from "./config";
import eth from "./eth";
import { getDate } from "@/utils/index.js";
import AESUtils from "@/utils/AES.js";
import { IPFS_PUBLIC_URL } from "@/api/User.js";
import IndexDBCache from "@/hooks/sql/useOrder.js";
import { bankAbi } from "./abi/bankAbi";
import {qutorAbi} from "./abi/qutorV2Abi"
import { showToast } from "vant";
const orderDB = new IndexDBCache();
const pageSize = 100;
const sumStart = (end) => {
  return end + 1 - pageSize > 0 ? end + 1 - pageSize : 0;
};
const pageNumAdd = (params) => {
  params.end = params.end + pageSize
  params.start = params.start + pageSize
  return params
}
const pageNum = (params) => {
  params.end = params.start - 1;
  params.start = sumStart(params.end);
  return params;
};

let provider, Contract, signer, ContractWithSinger;
try {
  provider = new ethers.providers.Web3Provider(window.ethereum);
  Contract = new ethers.Contract(
    bankContract,
    [
  "function advanceUnlock(uint256 lockId) nonpayable ",
  "function agent(address ) view returns (address )",
  "function allNormalTokenLockedCount() view returns (uint256 )",
  "function bbToken() view returns (address )",
  "function bindParent(address referrer) nonpayable ",
  "function btcbToken() view returns (address )",
  "function cumulativeBtcb() view returns (uint256 )",
  "function cumulativeLockInfo(address ) view returns (address token, uint256 amount)",
  "function developerAddress1() view returns (address )",
  "function developerAddress2() view returns (address )",
  "function developerAddress3() view returns (address )",
  "function developerAddress4() view returns (address )",
  "function editLock(uint256 lockId, uint256 newAmount, uint256 newUnlockDate) nonpayable ",
  "function getCumulativeNormalTokenLockInfo(uint256 start, uint256 end) view returns ((address token, uint256 amount)[] )",
  "function getCumulativeNormalTokenLockInfoAt(uint256 index) view returns ((address token, uint256 amount) )",
  "function getLockAt(uint256 index) view returns ((uint256 id, address token, address create, address owner, address receiveAddress, address referenceAddress, uint256 referenceRatio, uint256 amount, uint256 isRecoverLock, uint256 lockDate, uint256 tgeDate, uint256 tgeBps, uint256 cycle, uint256 cycleBps, uint256 unlockedAmount, uint256 price, uint256 alreadyUsdt, string description, string title) )",
  "function getLockById(uint256 lockId) view returns ((uint256 id, address token, address create, address owner, address receiveAddress, address referenceAddress, uint256 referenceRatio, uint256 amount, uint256 isRecoverLock, uint256 lockDate, uint256 tgeDate, uint256 tgeBps, uint256 cycle, uint256 cycleBps, uint256 unlockedAmount, uint256 price, uint256 alreadyUsdt, string description, string title) )",
  "function getLocksForToken(address token, uint256 start, uint256 end) view returns ((uint256 id, address token, address create, address owner, address receiveAddress, address referenceAddress, uint256 referenceRatio, uint256 amount, uint256 isRecoverLock, uint256 lockDate, uint256 tgeDate, uint256 tgeBps, uint256 cycle, uint256 cycleBps, uint256 unlockedAmount, uint256 price, uint256 alreadyUsdt, string description, string title)[] )",
  "function getTotalLockCount() view returns (uint256 )",
  "function lock(address receiveAddress, address referenceAddress, uint256 referenceRatio, uint256 amount, uint256 isOwner, uint256 unlockDate, bool isBuy, string description, string title) payable ",
  "function lpFee() view returns (uint24 )",
  "function normalLockCountForUser(address user) view returns (uint256 )",
  "function normalLockForUserAtIndex(address user, uint256 index) view returns ((uint256 id, address token, address create, address owner, address receiveAddress, address referenceAddress, uint256 referenceRatio, uint256 amount, uint256 isRecoverLock, uint256 lockDate, uint256 tgeDate, uint256 tgeBps, uint256 cycle, uint256 cycleBps, uint256 unlockedAmount, uint256 price, uint256 alreadyUsdt, string description, string title) )",
  "function normalLocksForUser(address user, uint256 start, uint256 end) view returns ((uint256 id, address token, address create, address owner, address receiveAddress, address referenceAddress, uint256 referenceRatio, uint256 amount, uint256 isRecoverLock, uint256 lockDate, uint256 tgeDate, uint256 tgeBps, uint256 cycle, uint256 cycleBps, uint256 unlockedAmount, uint256 price, uint256 alreadyUsdt, string description, string title)[] )",
  "function owner() view returns (address )",
  "function produceBB() view returns (uint256 )",
  "function queryBtcbPrcie() nonpayable returns (uint256 )",
  "function quoterV2() view returns (address )",
  "function receiveLocksForUser(address user, uint256 start, uint256 end) view returns ((uint256 id, address token, address create, address owner, address receiveAddress, address referenceAddress, uint256 referenceRatio, uint256 amount, uint256 isRecoverLock, uint256 lockDate, uint256 tgeDate, uint256 tgeBps, uint256 cycle, uint256 cycleBps, uint256 unlockedAmount, uint256 price, uint256 alreadyUsdt, string description, string title)[] )",
  "function receiveOwnerLocksForUser(address user, uint256 start, uint256 end) view returns ((uint256 id, address token, address create, address owner, address receiveAddress, address referenceAddress, uint256 referenceRatio, uint256 amount, uint256 isRecoverLock, uint256 lockDate, uint256 tgeDate, uint256 tgeBps, uint256 cycle, uint256 cycleBps, uint256 unlockedAmount, uint256 price, uint256 alreadyUsdt, string description, string title)[] )",
  "function recommendLocksForUser(address user, uint256 start, uint256 end) view returns ((uint256 id, address token, address create, address owner, address receiveAddress, address referenceAddress, uint256 referenceRatio, uint256 amount, uint256 isRecoverLock, uint256 lockDate, uint256 tgeDate, uint256 tgeBps, uint256 cycle, uint256 cycleBps, uint256 unlockedAmount, uint256 price, uint256 alreadyUsdt, string description, string title)[] )",
  "function renounceLockOwnership(uint256 lockId) nonpayable ",
  "function setDeveloperAddress(address addr1, address addr2, address addr3, address addr4) nonpayable ",
  "function setLpFee(uint24 _fee) nonpayable ",
  "function swapRouter() view returns (address )",
  "function totalLockCountForToken(address token) view returns (uint256 )",
  "function totalTokenLockedCount() view returns (uint256 )",
  "function transferLockOwnership(uint256 lockId, address newOwner) nonpayable ",
  "function transferOwnership(address newOwner) nonpayable ",
  "function unlock(uint256 lockId) nonpayable ",
  "function usdtToken() view returns (address )",
  "function userInfo(address ) view returns (uint256 lockBtcb, uint256 usdt, uint256 alreadyUsdt, uint256 profit, uint256 loss, uint256 bb)",
  "function vestingLock(address receiveAddress, address referenceAddress, uint256 referenceRatio, uint256 amount, uint256 isOwner, uint256 tgeDate, uint256 tgeBps, uint256 cycle, uint256 cycleBps, bool isBuy, string description, string title) payable ",
  "function withdrawableTokens(uint256 lockId) view returns (uint256 )"
],
    provider
  );
  signer = provider.getSigner();
  ContractWithSinger = Contract.connect(signer);
} catch (error) {}
const dataEth = {
  Contract,
  ContractWithSinger,

    async getPrice(){
    let price = 0
    try {
      let tokenIn = btcContract[0] 
      let tokenOut = usdtContract[0]
      let fee = 500
      let amountIn  = ethers.utils.parseUnits( '1',  btcContract[3]);
      price = await this.quoteExactInputSingle(tokenIn, tokenOut,amountIn, fee, 0, usdtContract[3])
    } catch (error) {
    }finally{
      store.commit("changeTokenPrice", price);
      return price
    }
  },
  async quoteExactInputSingle( tokenIn, tokenOut,amountIn, fee, priceLimit = 0, decimal) {
    const Contract = new ethers.Contract(qutorAbi.Contract, qutorAbi.contractAbi,  provider );
    
    let value = 0;
    try {
      let a = await Contract.callStatic.quoteExactInputSingle(
        [
        tokenIn,
        tokenOut,
        amountIn,
        fee,
        priceLimit
        ]
      );
      value = ethers.utils.formatUnits(a, decimal);
      return value;
    } catch (error) {
      value = ethers.utils.formatUnits(error.value.amountOut, decimal);
      return value;
    }
  },
  
  async getSystem() {
    let cumulativeBtcb = 0
    let produceBB = 0
    try {
      // btc价格
      cumulativeBtcb =  parseFloat(ethers.utils.formatUnits(await Contract.cumulativeBtcb(), btcContract[3])) 
      produceBB =parseFloat( ethers.utils.formatUnits(await Contract.produceBB(), bbContract[3]))
    } catch (err) {
    } finally {
      store.commit("changeCumulativeBtcb",cumulativeBtcb)
      store.commit("changeProduceBB",produceBB)
    }
  },
  
  async getUserInfo(accounts) {
    let obj = {}
    try {
      // btc价格
      let account = accounts || await eth.getAccount()
      let res = await Contract.userInfo(account)
      obj =  this.getUser(res)
    } catch (err) {
    } finally {
      store.commit("changeUserInfo",obj)
      return obj;
    }
  },
  async getParent(account) {
    let parent = ''
    try {
      let myAccount = await eth.getAccount();
      let realAccount = account || myAccount
      // btc价格
      parent = await Contract.agent(realAccount)
      if(parent==store.state.address0){
        parent = ''
      }
    } catch (err) {
    } finally {
      store.commit("changeMyParent", parent);
      return parent;
    }
  },
  // 获取用户参与记录
  async normalLocksForUser(accounts) {
    await orderDB.initDB();
    let account = accounts || await eth.getAccount()
    // await orderDB.searchCount('recordList', 'owner', account) ||
    let start =  0
    let params = {
      start: start, 
      end:start + pageSize - 1
    };
    const onload = async () => {
      try {
        let data = await ContractWithSinger.normalLocksForUser(account,params.start, params.end);
        let allPromise = [];
        data.forEach((e) => {
            allPromise.push(this.getLockList(e));
        });
        let allData = await Promise.all(allPromise);
        await allData.forEach(async (obj, index) => {
          await orderDB.updateData("lockList", obj);
        });
        if (data.length == pageSize) {
          params = pageNumAdd(params)
          await onload();
        } else {

        }
      } catch (err) {
      } finally {
      }
    };
    await onload();
  },
 generateRandom() {
	return Math.random().toString(16).slice(2);  
},
 getUser (res,account) {
    try {
      let accountObj = {}
      if(account){
        accountObj.address =account.toLowerCase()
      }
      return {
        lockBtcb:parseFloat(ethers.utils.formatUnits(res.lockBtcb, btcContract[3])),
        usdt:parseFloat(ethers.utils.formatUnits(res.usdt, usdtContract[3])),
        alreadyUsdt:parseFloat(ethers.utils.formatUnits(res.alreadyUsdt, usdtContract[3])),
        profit:parseFloat(ethers.utils.formatUnits(res.profit, usdtContract[3])),
        loss:parseFloat(ethers.utils.formatUnits(res.loss, usdtContract[3])),
        bb:parseFloat(ethers.utils.formatUnits(res.bb, bbContract[3])),
      };
    } catch (err) {
      return {};
    }
  },
  async getLockList(res) {
    try {
      return {
              //  //ID
              //  uint256 id;
              //  //token合约地址
              //  address token;
              //  //创建人
              //  address create;
              //  //所属人
              //  address owner;
              //  //接收地址
              //  address receiveAddress;
              //  //推荐人地址
              //  address referenceAddress;
              //  //推荐人比例(万分之)
              //  uint256 referenceRatio;
              //  //数量
              //  uint256 amount;
              //  //是否所有者提前收回锁 1 是
              //  uint256 isRecoverLock;
              //  //锁定时间
              //  uint256 lockDate;
              //  //开始释放时间 or 解锁时间
              //  uint256 tgeDate; // TGE date for vesting locks, unlock date for normal locks
              //  //首次释放比例
              //  uint256 tgeBps; // In bips. Is 0 for normal locks
              //  //循环间隔时间
              //  uint256 cycle; // Is 0 for normal locks
              //  //循环释放比例
              //  uint256 cycleBps; // In bips. Is 0 for normal locks
              //  //已解锁数量
              //  uint256 unlockedAmount;
              //  //锁定时btcb价格
              //  uint256 price;
              //  //已领取的USDT数量
              //  uint256 alreadyUsdt;
              //  //备注
              //  string description;
              //  //标题
              //  string title;
        id: Number(ethers.utils.formatUnits(res.id, 0)),
        token: res.token.toLowerCase(),
        create: res.create.toLowerCase(),
        owner: res.owner.toLowerCase(),
        receiveAddress: res.receiveAddress.toLowerCase(),
        referenceAddress: res.referenceAddress.toLowerCase(),
        referenceRatio:parseFloat(ethers.utils.formatUnits(res.referenceRatio, 4)),
        amount:parseFloat(ethers.utils.formatUnits(res.amount, btcContract[3])),
        isRecoverLock:ethers.utils.formatUnits(res.isRecoverLock, 0),
        lockDate: getDate(res.lockDate * 1000),
        tgeDate: getDate(res.tgeDate * 1000),
        tgeBps:parseFloat(ethers.utils.formatUnits(res.tgeBps, 4)),
        cycle:parseFloat(ethers.utils.formatUnits(res.cycle, 0)),
        cycleBps:parseFloat(ethers.utils.formatUnits(res.cycleBps, 4)),
        unlockedAmount:parseFloat(ethers.utils.formatUnits(res.unlockedAmount, btcContract[3])),
        price :parseFloat(ethers.utils.formatUnits(res.price, usdtContract[3])),
        alreadyUsdt:parseFloat(ethers.utils.formatUnits(res.alreadyUsdt, usdtContract[3])),
        description:res.description,
        title:res.title,
      };
    } catch (err) {
      return null;
    }
  },
  // 获取本地详情
  async getLockDetail(id) {
    let obj = {};
    try {
      await orderDB.initDB();
      obj = await orderDB.getDataByKey("lockList", Number(id));
      if (obj && obj.length > 0) {
        return obj[0];
      }
    } catch (error) {
      debugger
    }
    return obj;
  },
  
  // 单独获取一个订单详情
  async getLockById(id) {
    let obj = {};
    try {
      let item = await Contract.getLockById(id);
      obj = await this.getLockList(item,true);
    } catch (err) {
    } finally {
      return obj;
    }
  },
};
export default dataEth;
